#include "ads1110.h"
 
#define  REFER_MV 2048      ///< Reference millivolt voltage  
static const float rate_div_f[4] = {2048.0f,8192.0f,16384.0f,32768.0f};  ///<
static const float gain_div_f[4] = {1.0f,2.0f,4.0f,8.0f};    ///<
 
int com_ads1110_init(com_ads1110_dev_t *dev, uint8_t dev_addr, com_ads1110_write_callback_t w_cb, com_ads1110_read_callback_t r_cb)
{
    if((dev == NULL) || (w_cb == NULL) || (r_cb == NULL)){
        return COM_ERROR_NULL;
    }
 
    dev->dev_addr         = dev_addr; 
    dev->res_val[0]       = 1.0f;
    dev->w_cb             = w_cb;
    dev->r_cb             = r_cb;
    dev->cfg_reg[0]       = 0x8c;
    dev->cfg_reg_t[0]     = dev->cfg_reg[0];
    dev->config[0].rate_i = COM_DEV_ADS1110_RATE_15SPS;
    dev->config[0].gain_i = COM_DEV_ADS1110_GAIN_1;
    dev->config[0].mode_i = COM_DEV_ADS1110_MODE_CONTINU;
 
    return COM_SUCCESS;
}
 
int com_ads1110_write_cfg_reg(com_ads1110_dev_t *dev)
{
    if((dev == NULL) || (dev->w_cb == NULL)){
        return COM_ERROR_NULL;
    }
    dev->cfg_reg_t[0]=dev->cfg_reg[0];
 
    dev->config[0].rate_i  = (dev->cfg_reg_t[0] >> 2) & 0x03;              
    
    dev->config[0].gain_i  = dev->cfg_reg_t[0]&0x03;                
                       
    dev->config[0].mode_i  = (dev->cfg_reg_t[0] >> 4) & 0x01;            
 
    return dev->w_cb(dev->dev_addr, dev->cfg_reg, 1);
}
 
int com_ads1110_read_cfg_reg(com_ads1110_dev_t *dev)
{
    if((dev == NULL) || (dev->r_cb == NULL)){
        return COM_ERROR_NULL;
    }
 
    int res;
    res=dev->r_cb(dev->dev_addr, dev->tm_reg, 3);
    if(res != COM_SUCCESS){
        return res;
    }
    dev->cfg_reg[0]   = dev->tm_reg[2];
    dev->cfg_reg_t[0] = dev->tm_reg[2];
 
    dev->config[0].rate_i  = (dev->cfg_reg_t[0]>>2)&0x03;         
     
    dev->config[0].gain_i  = dev->cfg_reg_t[0]&0x03;                          
 
    dev->config[0].mode_i  = (dev->cfg_reg_t[0]>>4)&0x01;                                     
 
    return COM_SUCCESS;
}
 
int com_ads1110_read_voltage(com_ads1110_dev_t *dev, float *mv)
{
    if((dev == NULL) || (dev->r_cb == NULL) || (mv == NULL)){
        return COM_ERROR_NULL;
    }
 
    int      res;
    uint16_t tm_data_i; 
 
    res = dev->r_cb(dev->dev_addr, dev->tm_reg, 3);
    if(res != COM_SUCCESS)
    {
        return res;
    }
    tm_data_i=(dev->tm_reg[0] << 8) + dev->tm_reg[1];
 
    // juage 
    *mv=1.0f*tm_data_i*(REFER_MV / rate_div_f[dev->config[0].rate_i]) / gain_div_f[dev->config[0].gain_i];
 
    return COM_SUCCESS;
}
 
int com_ads1110_read_current(com_ads1110_dev_t *dev, float *ma)
{
    if(ma == NULL){
        return COM_ERROR_NULL;
    }
 
    int res;
    float tm_f[1];
 
    res = com_ads1110_read_voltage(dev, tm_f);
    if(res == COM_SUCCESS){
        if(0.0f < dev->res_val[0]) {   
            *ma=tm_f[0] / dev->res_val[0];
            return COM_SUCCESS;
        } else {
            return COM_ERROR_INVALID_DATA;
        }
    } else {  
        return res;
    }
}
 
int com_ads1110_set_rate(com_ads1110_dev_t *dev, COM_DEV_ADS1110_RATE_T rate)
{
    if(dev == NULL ){
        return COM_ERROR_NULL;
    }
 
    dev->cfg_reg[0] &= 0xF3;                ///< 0Bxxxx,00xx
    dev->cfg_reg[0] |= (rate << 2);         ///< 0Bxxxx,yyxx   rate=yy
 
    return COM_SUCCESS;
}
 
int com_ads1110_get_rate(com_ads1110_dev_t *dev, COM_DEV_ADS1110_RATE_T *rate)
{
    if(dev == NULL || rate == NULL){
        return COM_ERROR_NULL;
    }
 
    //*rate = dev->cfg_reg_t[0];              ///< 0Bxxxx,yyxx   rate=yy
    //*rate = *rate>>2;                       ///< 0B00xx,xxyy
    //*rate &= 0x03;                          ///< 0B0000,00yy
    *rate=dev->config[0].rate_i;
 
    return COM_SUCCESS;
}
 
int com_ads1110_set_gain(com_ads1110_dev_t *dev, COM_DEV_ADS1110_GAIN_T gain)
{
    if(dev == NULL){
        return COM_ERROR_NULL;
    }
 
    dev->cfg_reg[0] &= 0xFC;                ///< 0Bxxxx,xx00
    dev->cfg_reg[0] |= gain;                ///< 0Bxxxx,xxyy   gain=yy
 
    return COM_SUCCESS;
}
 
int com_ads1110_get_gain(com_ads1110_dev_t *dev, COM_DEV_ADS1110_GAIN_T *gain)
{
    if(dev == NULL || gain == NULL){
        return COM_ERROR_NULL;
    }
 
    //*gain = dev->cfg_reg_t[0];             ///< 0Bxxxx,xxyy   gain=yy
    //*gain &= 0x03;                         ///< 0B0000,00yy   
    *gain=dev->config[0].gain_i;
 
    return COM_SUCCESS;
}
 
int com_ads1110_set_mode(com_ads1110_dev_t *dev,COM_DEV_ADS1110_MODE_T  mode)
{
    if(dev == NULL){
        return COM_ERROR_NULL;
    }
 
    dev->cfg_reg[0] &= 0xEF;                ///< 0Bxxx0,xxxx
    dev->cfg_reg[0] |= (mode<<4);           ///< 0Bxxxy,xxxx   mode=y
 
    return COM_SUCCESS;
}
 
int com_ads1110_get_mode(com_ads1110_dev_t *dev,COM_DEV_ADS1110_MODE_T *mode)
{
    if(dev == NULL || mode == NULL){
        return COM_ERROR_NULL;
    }
 
    *mode=dev->config[0].mode_i;
 
    return COM_SUCCESS;
}
 
int com_ads1110_set_res_val(com_ads1110_dev_t *dev, float v)
{
    if(dev == NULL){
        return COM_ERROR_NULL;
    }
    if(v <= 0){
        return COM_ERROR_INVALID_DATA;
    }
 
    dev->res_val[0] = v;
 
    return COM_SUCCESS;
}
 
int com_ads1110_get_res_val(com_ads1110_dev_t *dev,float *v)
{
    if(dev == NULL || v == NULL){
        return COM_ERROR_NULL;
    }
 
    *v = dev->res_val[0];
 
    return COM_SUCCESS;
}
